#include "Barde.h"

//#include "ListeSorts.h"
#include "LireSorts.h"

#include "lib.h"

#include "ATL.h"

#include <iomanip>

#include <algorithm>

using namespace std;
using namespace boost::assign;

const unsigned Barde::nbrCompetences = 17;

const unsigned Barde::nbrRestrictions = 0;

const unsigned Barde::ppAlloues = 70;

const vector<CompetenceClasse> Barde::Comp = list_of
  ( CompetenceClasse( "Amitié avec les animaux"           , 10 ) )
  ( CompetenceClasse( "Barde en armure"                   , 10 ) )
  ( CompetenceClasse( "Contre-chant"                      , 10 ) )
  ( CompetenceClasse( "Détecter des bruits"               ,  5, true, 20 ) ) // base = 20%
  ( CompetenceClasse( "Détection de la magie"             , 10, true, 10 ) ) // base = 10%
  ( CompetenceClasse( "Grimper"                           ,  5, true, 50 ) ) // base = 50%
  ( CompetenceClasse( "Histoire"                          , 10 ) )
  ( CompetenceClasse( "Inspiration"                       ,  5 ) )
  ( CompetenceClasse( "Lire des langues inconnues"        ,  5, true,  5 ) ) // base = 5%
  ( CompetenceClasse( "Manipulation"                      ,  5 ) )
  ( CompetenceClasse( "Résistance aux charmes"            ,  5 ) )
  ( CompetenceClasse( "Résistance aux sons"               ,  5 ) )
  ( CompetenceClasse( "Sorts de mage"                     , 10 ) )
  ( CompetenceClasse( "Spécialisation"                    , 10 ))
  ( CompetenceClasse( "Utilisation de parchemins (niv 10)",  5 ) )
  ( CompetenceClasse( "Utilisation de parchemins"         , 10 ) )
  ( CompetenceClasse( "Vol à la tire"                     , 10, true, 10 ) );  // base = 10%

const vector< Prerequis > Barde::Limites = list_of
  ( Prerequis( 1, 12 ) )
  ( Prerequis( 3, 13 ) )
  ( Prerequis( 5, 15 ) );

const set< string > Barde::RacesAdmises = list_of
  ( "Humain" ) ( "Demi-Elfe" );

/** Constructeur usuel.
 * Permet la construction d'un barde de A à Z, càd on détermine ici
 * les restrictions, puis les compétences.
 *
 * @param[in] xp le nombre de pts d'expérience du Barde.
 * @param[in] trait les traits du Barde, le 7ème contient le score de
 * force exceptionnel, fixé à 0 si non applicable.
 * @param[in] PP nombre de points de personnage (PP) à disposition
 * pour la céation du Barde.
 * @param[in] race nom de la race du personnage.
 */
Barde::Barde(unsigned xp, const vector< unsigned >& trait,
	     unsigned& PP, const string& race)
  : Classe( xp, Roublards, "Barde" )
{
  /*Debug::*/empileNiveau( &elementaire );
  //NomClasse = "Barde";
  NombrePPsAlloues = ppAlloues;
  PP += NombrePPsAlloues;

  NombreTotalCompetences  = nbrCompetences;
  NombreTotalRestrictions = nbrRestrictions;
  NombreTotalEnsembles    = 0;
  NombreMaxCompetences    = 0;
  ListesCompetences       = list_of< vector< CompetenceClasse > >( Comp );
  PrerequisClasse         = list_of< vector< Prerequis > >( Limites );
  RacesAdmisesClasse      = list_of< set< string > >( RacesAdmises );

  blank() << setfill('*') << setw(56) << '*' << setfill(' ') << endmsg;
  blank() << "Création d'un barde" << endmsg << endmsg;

  construitClasse( PP, trait, race );

  blank() << endmsg << setfill('*') << setw(56) << '*' << setfill(' ')
	      << endmsg;
  calculNiveau();
  calculNivMag();

  if ( ! possedePourcent() )
    PP += 20;
  
 /*Debug::*/depileNiveau();
}

/** Constructeur simplifié.
 * Permet de construire un Barde lors de la lecture d'un fichier xml.
 *
 * @param[in] xp le nombre de pts d'expérience du Barde.
 * @param[in] trait les traits du Barde, le 7ème contient le score de
 * force exceptionnel, fixé à 0 si non applicable.
 * @param[in] race nom de la race du personnage.
 */
Barde::Barde( unsigned xp )
  : Classe( xp, Roublards, "Barde" )
{
  //NomClasse = "Barde";
  NombrePPsAlloues = ppAlloues;

  NombreTotalCompetences  = nbrCompetences;
  NombreTotalRestrictions = nbrRestrictions;
  NombreTotalEnsembles    = 0;
  NombreMaxCompetences    = 0;
  ListesCompetences       = list_of< vector< CompetenceClasse > >( Comp );
  PrerequisClasse         = list_of< vector< Prerequis > >( Limites );
  RacesAdmisesClasse      = list_of< set< string > >( RacesAdmises );

  calculNiveau();
  calculNivMag();
}

/**
 * Constructue utilisé lors de la création d'un Barde avec l'interface
 * graphique. Son fonctionnement est très similaire au constructeur
 * simplifié, mais ici le nombre de XP n'est pas donné, il est
 * déterminé pus tard dans le processus de création.
 *
 * @param[in] trait les traits du Barde, le 7ème contient le score de
 * force exceptionnelle, fixé à 0 si non applicable.
 * @param[in] UI bool qui permet de contrôler que c'est bien le mode
 * de créatioon voulu, est là pour des raisons historiques.
 * @param[in] race nom de la race du personnage.
 */
Barde::Barde( const bool& UI )
  : Classe( 1, Roublards, "Barde" )
{
  if (!UI)
    {
      error() << "Création du personnage impossible" << endmsg;
      exit(1);
    }

  //NomClasse = "Barde";
  NombrePPsAlloues = ppAlloues;

  NombreTotalCompetences  = nbrCompetences;
  NombreTotalRestrictions = nbrRestrictions;
  NombreTotalEnsembles    = 0;
  NombreMaxCompetences    = 0;
  ListesCompetences       = list_of< vector< CompetenceClasse > >( Comp );
  PrerequisClasse         = list_of< vector< Prerequis > >( Limites );
  RacesAdmisesClasse      = list_of< set< string > >( RacesAdmises );

  calculNiveau();
  calculNivMag();
}

/**
 * Constructeur de "copie", destiné à être utilisé depuis MetaClasse.
 *
 * @param[in] ptr pointeur sur un objet de type Classe (MetaClasse en
 * fait).
 */
Barde::Barde(Classe *ptr)
  : Classe( *ptr )
{
  NomClasse = "Barde";
  NombrePPsAlloues = ppAlloues;

  NombreTotalCompetences  = nbrCompetences;
  NombreTotalRestrictions = nbrRestrictions;
  NombreTotalEnsembles    = 0;
  NombreMaxCompetences    = 0;
  ListesCompetences       = list_of< vector< CompetenceClasse > >( Comp );
  PrerequisClasse         = list_of< vector< Prerequis > >( Limites );
  RacesAdmisesClasse      = list_of< set< string > >( RacesAdmises );

  calculNiveau();
  calculNivMag();
}

Barde::~Barde()
{}

void Barde::calculNiveau()
{
  if (XP < 75000)
    {
      unsigned i;
      for (i = 0; i < 5; i++)
	{
	  if (XP < (unsigned) 1250 * puissance(2, i))
	    break;
	}
      Niveau = i + 1;
    }
  else if (XP < 70000)
    Niveau = 7;
  else if (XP < 110000)
    Niveau = 8;
  else if (XP < 160000)
    Niveau = 9;
  else if (XP < 220000)
    Niveau = 10;
  else
      Niveau = (XP - 220000) / 220000 + 11;
}

/**
 * Ici sont appliqués les modifications aux talents de barde dues à la Race
 * et à la Dextérité.
 */
void Barde::appliquerModif( const string& nomRace, const unsigned& dexterite )
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Barde::appliquerModif -> début" << endmsg;
  
  vector< int > *comp_bonus;

  determinerScoresAjustes( nomRace, dexterite, comp_bonus );

//     if (type == "Nain")
//     {
//       comp_bonus[4]  += 5;   // détection de la magie
//       comp_bonus[5]  -= 10;  // escalade
//       comp_bonus[8]  -= 5;   // lire des langues inconnues
//     }
//   else if (type == "Elfe")
//     {
//       comp_bonus[3]  += 5;   // détection des bruits
//       comp_bonus[4]  += 10;  // détection de la magie
//       comp_bonus[16] += 5;   // vol à la tire
//     }
//   else if (type == "Gnome")
//     {
//       comp_bonus[3]  += 10;  // détection des bruits
//       comp_bonus[4]  += 5;   // détection de la magie
//       comp_bonus[5]  -= 15;  // escalade
//     }
//   else if (type == "Demi-Elfe")
//     {
//       comp_bonus[4]  += 5;   // détection de la magie
//       comp_bonus[16] += 10;  // vol à la tire
//     }
//   else if (type == "Demi-Orque")
//     {
//       comp_bonus[3]  += 5;   // détection des bruits
//     }
//   else if (type == "Hobbit")
//     {
//       comp_bonus[3]  += 5;   // détection des bruits
//       comp_bonus[4]  += 5;   // détection de la magie
//       comp_bonus[5]  -= 15;  // escalade
//       comp_bonus[8]  -= 5;   // lire des langues inconnues
//       comp_bonus[16] += 5;   // vol à la tire
//     }

//   switch(Traits[1])
//     {
//     case 9:
//       comp_bonus[5]  -= 10;  // escalade
//       comp_bonus[16] -= 15;  // vol à la tire
//       break;
//     case 10:
//       comp_bonus[5]  -= 5;   // escalade
//       comp_bonus[16] -= 10;  // vol à la tire
//       break;
//     case 11:
//       comp_bonus[16] -= 5;   // vol à la tire
//       break;
//     case 17:
//       comp_bonus[5]  += 5;   // escalade
//       comp_bonus[16] += 5;   // vol à la tire
//       break;
//     case 18:
//       comp_bonus[5]  += 10;  // escalade
//       comp_bonus[16] += 10;  // vol à la tire
//       break;
//     case 19:
//       comp_bonus[5]  += 15;  // escalade
//       comp_bonus[16] += 15;  // vol à la tire
//       break;
//     case 20:
//       comp_bonus[5]  += 20;  // escalade
//       comp_bonus[16] += 20;  // vol à la tire
//       break;
//     case 21:
//       comp_bonus[5]  += 20;  // escalade
//       comp_bonus[16] += 20;  // vol à la tire
//       break;
//     case 22:
//       comp_bonus[5]  += 25;  // escalade
//       comp_bonus[16] += 25;  // vol à la tire
//       break;
//     }

  map< unsigned, unsigned > correspondace = map_list_of
    ( 3,  3)
    ( 4,  4)
    ( 5,  7)
    ( 8,  8)
    (16, 12);

  unsigned combien_comp(Competences.size()), valeur;
  vector<unsigned> tmp;
  for (unsigned i(0); i < combien_comp; i++)
    {
      valeur = Competences[i];
      if (Comp[valeur].pourcentage())
	{
	  Competences[i + 1] += comp_bonus -> at( correspondace[valeur] );
	  i++;
	}
    }

  func() << "Barde::appliquerModif -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**
 * Ici on peut augmenter les talents liés à un pourcentage à chaque
 * passage de niveau et à la création.
 *
 * Une sauvegarde de l'état courant est faite avant de modifier quoi
 * que ce soit, et ensuite on afiche un récapitulatif des changements,
 * qui doivent être validés.
 */
void Barde::augmenterTalents( const string& nomRace,
			      const vector< unsigned >& traits, 
			      const bool& lvl_up )
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Barde::augmenterTalents -> début" << endmsg;

  if ( ! possedePourcent() )
    {
      func() << "Barde::augmenterTalents -> fin" << endmsg;
      return;
    }

  vector<unsigned> quelle, quelleValeur[2];
  unsigned bonus( pourcent( lvl_up ) );

  unsigned taille( tailleCompetences() ), nbr( 0 ), depense, laquelle,
    encore(1), i, j(0);

  bool pourcent( false );
  
  for (unsigned i(0); i<taille; i++)
    {
      debug() << Competences[i];
      if (Comp[Competences[i]].pourcentage())
	{
	  debug() << " -> oui";
	  quelle.push_back(Competences[i]);
	  quelleValeur[0].push_back(Competences[i+1]);
	  quelleValeur[1].push_back(Competences[i+1]);
	  i++;
	  nbr++;
	}
      debug() << endmsg;
    }

  do
    {
      unsigned pps(bonus);
      if (lvl_up)
	pps = 15;
      blank() << "Tu as " << pps << " points à dépenser dans les compétences"
		  << " suivantes:" << endmsg;
      for (i = 0; i<nbr; i++)
	{
	  debug() << quelle[i] << " => " << Comp[quelle[i]].nom() << endmsg;
	  blank() << i+1 << " " << Comp[quelle[i]].nom() << " "
		      << quelleValeur[0][i] << "%" << endmsg;
	}
      
      string poubelle;
      
      while(pps != 0)
	{
	  
	  laquelle =
	    demanderUnsignedBorne("Quelle compétence veux-tu améliorer? ",
				    1, nbr);
	  
	  depense = demanderUnsignedBorne("(" + ecrireString( pps ) + ") De combien? ", 0, pps);
	  
	  quelleValeur[1][laquelle-1] += depense;
	  pps -= depense;
	}
      
      for (i = 0; i < nbr; i++)
	{
	  blank() << Comp[quelle[i]].nom() << " "
		  << quelleValeur[0][i] << " -> " << quelleValeur[1][i]
		  << endmsg;
	}

      blank() << endmsg <<  "1 pour continuer, 2 pour recommencer" << endmsg;
      encore = demanderUnsignedBorne("Choix ", 1, 2);
      if ( encore == 1 )
	break;
    }
  while ( encore == 2 );

  j = 0;
  
  for (i = 0; i < taille; i++)
    {
      if (Competences[i] == quelle[j])
	{
	  debug() << Comp[quelle[j]].nom() << " "
		      << quelleValeur[0][j] << " -> " << quelleValeur[1][j]
		      << endmsg;
	  lfunc() << nomCompetence( i, nomRace, traits, pourcent ) << " -> ";
	  Competences[i + 1] = quelleValeur[1][j];
	  lfunc() << nomCompetence( i, nomRace, traits, pourcent ) << endmsg;
	  j++;
	}
    }

  func() << "Barde::augmenterTalents -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

void Barde::js(unsigned *tab) const
{
  *(tab + 0) = 13; // Paralysie, Poison ou Mort magique
  *(tab + 1) = 14; // Bâton, batonnet baguette
  *(tab + 2) = 12; // Pétrification ou Métamorphose
  *(tab + 3) = 16; // Souffles
  *(tab + 4) = 15; // Sorts
  
  unsigned cat;
  if (Niveau <= 4)
    cat = 0;
  else  if (Niveau <= 8)
    cat = 1;
  else  if (Niveau <= 12)
    cat = 2;
  else  if (Niveau <= 16)
    cat = 3;
  else  if (Niveau <= 20)
    cat = 4;
  else
    cat = 5;

  *(tab + 0) -= cat;
  *(tab + 1) -= 2 * cat;
  *(tab + 2) -= cat;
  *(tab + 3) -= cat;
  *(tab + 4) -= 2 * cat;
}

unsigned Barde::calculeTAc0() const
{
  unsigned mod_niveau((Niveau - 1) / 2);

  return 20 - mod_niveau;
}

void Barde::calculNivMag()
{
  /*Debug::*/empileNiveau( &fonction );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(fonction);
  func() << "Barde::calculNivMag -> début" << endmsg;
  bool a_des_sorts(false);

  vector<unsigned>::const_iterator it, Begin(Competences.begin()),
    End(Competences.end());

  it = find(Begin, End, 12);

  if (it != End)
    {
      a_des_sorts = true;
      debug() << "A accès aux sorts de mages" << endmsg;
    }

  if (a_des_sorts)
    {
      if (Niveau < 4)
	NiveauMagique = (Niveau) / 2;
      else if (Niveau < 19)
	NiveauMagique = (Niveau + 2) / 3;
      else
	NiveauMagique = 6;  
    }
  else
    NiveauMagique = 0;

  
  func() << "Barde::calculNivMag -> fin" << endmsg;
  /*Debug::*/depileNiveau();//dout.setLevel(etat_precedent);
}

/**
 * Il faut ici regarder dans SortsClasse pour savoir quels sont les sorts
 * contenus dans le Livre de Sorts du magicien.
 * 
 * Le tri se fait d'abord par Ecole, puis par Niveau et ensuite dans l'ordre
 * alphabétique.
 *
 * La variable Classe::fonction permet d'afficher :
 *
 * - FUNC : début et fin de l'exécution de la méthode
 *
 * - DEBUG : écrasement du fichier, nombre de sorts, sort courant
 */
void Barde::ecrireSorts( const string& nom_fichier, const bool& ecrase,
			 const unsigned& ) const
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Barde::ecrireSorts -> début" << endmsg;

  ofstream sortie;
  if (ecrase)
    {
      debug() << "Ecrasement du fichier " << nom_fichier << endmsg;
      sortie.open(nom_fichier.c_str());
    }
  else
    {
      sortie.open(nom_fichier.c_str(), ios::app);
      sortie << "\\newpage" << endl;
    }

  if (NiveauMagique == 0)
    {
      sortie.close();
      func() << "Barde::ecrireSorts -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      return;
    }

  sortie << "\\section*{Livre de sorts - Barde}" << endl;

  vector< unsigned > vec;

  sortsParNiveau( vec, -1u );
  
  sortie << "\\begin{center}" << endl 
	 << "\\begin{tabular*}{10cm}{@{\\extracolsep{\\fill}} l r}"
	 << endl << "\\multicolumn{2}{c}{Nombre de sorts par jour} \\\\"
	 << "\\hline \\\\ \\vspace{1mm}" << endl;
  for (unsigned i(0); i < NiveauMagique; i++)
    sortie << "Niveau " << i+1 << " & " << vec[i] << " \\\\" << endl;
  sortie << "\\end{tabular*}" << endl << "\\end{center}" << endl;

  unsigned taille( nbrSortsConnus() ), i, courant(10), niv_courant(10);
  vector< CompetenceClasse > nomEcoles =
    list_of< CompetenceClasse >( CompetenceClasse( "Abjuration" ) )
    ( CompetenceClasse( "Altération", "Alteration", 0 ) )
    ( CompetenceClasse( "Conjuration - Convocation", "Conjuration", 0 ) )
    ( CompetenceClasse( "Divination" ) )
    ( CompetenceClasse( "Enchantement - Charme", "Enchantement", 0 ) )
    ( CompetenceClasse( "Illusion" ) )
    ( CompetenceClasse( "Invocation - Evocation", "Invocation", 0 ) )
    ( CompetenceClasse( "Nécromancie", "Necromancie", 0 ) );

  debug() << "nbr de sorts = " << taille << endmsg;

  for(i = 0; i < taille; i++)
    {
      if (SortsClasse[i].ecole() != courant)
	{
	  courant = SortsClasse[i].ecole();
	  //afficheAccent(nom_ecoles[courant])
	  sortie << "\\subsection*{" << nomEcoles[ courant ] . nom()
		 << "}" << endl;
	}
      if (SortsClasse[i].niveau() != niv_courant)
	{
	  niv_courant = SortsClasse[i].niveau();
	  sortie << "\\subsubsection*{Niveau " << niv_courant << "}" << endl;
	}

      //supprimeAccents(nom_ecoles[courant])
      sortie << "\\input{../../Sorts-mage/" << nomEcoles[ courant ] . aliasNom()
	     << "/sort_" << niv_courant << "_" << SortsClasse[i].numero()
	     << ".inc.tex}" << endl;
    }

  sortie.close();

  func() << "Barde::ecrireSorts -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

void Barde::sortsParNiveau( vector< unsigned >& sorts,
			    const unsigned& ) const
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Barde::nbrSort -> début" << endmsg;

  vector< unsigned > tmp( 6, 0 );
  func() << "Nbr de niveaux de sort = " << NiveauMagique << endmsg;

  switch(Niveau)
    {
    case 2:
      tmp[0] = 1;
      break;
    case 3:
      tmp[0] = 2;
      break;
    case 4:
      tmp[0] = 2;
      tmp[1] = 1;
      break;
    case 5:
      tmp[0] = 3;
      tmp[1] = 1;
      break;
    case 6:
      tmp[0] = 3;
      tmp[1] = 2;
      break;
    case 7:
      tmp[0] = 3;
      tmp[1] = 2;
      tmp[2] = 1;
      break;
    case 8:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 1;
      break;
    case 9:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 2;
      break;
    case 10:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 2;
      tmp[3] = 1;
      break;
    case 11:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 3;
      tmp[3] = 1;
      break;
    case 12:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 3;
      tmp[3] = 2;
      break;
    case 13:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 3;
      tmp[3] = 2;
      tmp[4] = 1;
      break;
    case 14:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 3;
      tmp[3] = 3;
      tmp[4] = 1;
      break;
    case 15:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 3;
      tmp[3] = 3;
      tmp[4] = 2;
      break;
    case 16:
      tmp[0] = 4;
      tmp[1] = 3;
      tmp[2] = 3;
      tmp[3] = 3;
      tmp[4] = 2;
      tmp[5] = 1;
      break;
    case 17:
      tmp[0] = 4;
      tmp[1] = 4;
      tmp[2] = 3;
      tmp[3] = 3;
      tmp[4] = 3;
      tmp[5] = 1;
      break;
    case 18:
      tmp[0] = 4;
      tmp[1] = 4;
      tmp[2] = 4;
      tmp[3] = 3;
      tmp[4] = 3;
      tmp[5] = 2;
      break;
    case 19:
      tmp[0] = 4;
      tmp[1] = 4;
      tmp[2] = 4;
      tmp[3] = 4;
      tmp[4] = 3;
      tmp[5] = 2;
      break;
    default:
      tmp[0] = 4;
      tmp[1] = 4;
      tmp[2] = 4;
      tmp[3] = 4;
      tmp[4] = 4;
      tmp[5] = 3;
      break;
    }

  sorts.assign( tmp.begin(), tmp.end() );
  sorts.resize( NiveauMagique );

  func() << "Barde::nbrSort -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**
 * Permet de gérer l'ajout de sorts au livre du magicien
 *
 * La variable Classe::fonction permet d'afficher
 *
 * FUNC  : les messages de début - fin de la méthode
 *
 * LFUNC : les écoles auxquelles le Barde a accès
 *
 * DEBUG : numéro du dernier sort, sort écrit, sorts triés
 */
void Barde::ajoutSorts()
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Barde::ajoutSorts -> début" << endmsg;
  
  unsigned nbr, dernier, i, j, k, nbrSorts;
  string ecole;

  const LireSorts * liste = initLectureSortXML();

  if ( liste == 0 )
    {
      error() << "initLectureSortsXML : obtenu un pointeur nul" << endmsg;
      func() << "Barde::ajoutSorts -> début" << endmsg;
      /*Debug::*/depileNiveau();
      return;
    }

  const vector< SortsEcoles > * sortsParNiveauEcole;

  if (NiveauMagique == 0)
    {
      debug() << "Niveau magique = 0" << endmsg;
      return;
    }
  for (i = 0; i < 8; i++)
    {
      for ( j = 1; j <= NiveauMagique; j++ )
	{
	  blank() << "Niveau " << j << " :" << endmsg;
	  sortsParNiveauEcole = liste -> listeSorts( i, j - 1 );
	  if ( sortsParNiveauEcole == 0 )
	    {
	      warning() << "LireSorts::listeSorts( unsigned, unsigned ) "
			<< "a renvoyé un pointeur nul" << endmsg;
	      continue;
	    }
	  nbrSorts = sortsParNiveauEcole -> size();
	  for ( k = 0; k < nbrSorts; k++ )
	    {
	      blank() << setw( 2 )
		      << sortsParNiveauEcole -> at( k ) . numero() + 1
		      << ' ' << sortsParNiveauEcole -> at( k ) . nom()
		      << endmsg;
	    }
	  //dernier = afficheSorts(i, j);
	  dernier = ++k;
	  
	  debug() << "dernier = " << dernier << endmsg;
	  
	  if (dernier > 0)
	    {
	      blank() << setw(2) << dernier + 1 << " Aucun" << endmsg;
	      do
		{
		  nbr = demanderUnsignedBorne("Entrer nouveau sort : ", 1,
						dernier + 1);
		  if (nbr != dernier + 1)
		    {
		      debug() << "Ajout du sort " << Sort(i, j, nbr - 1)
				      << endmsg;
		      SortsClasse.push_back(Sort(i, j, nbr - 1));
		    }
		}
	      while(nbr != dernier + 1);
	    }
	}
    }
  
  vector<Sort>::iterator Begin, End, it;
  Begin = SortsClasse.begin();
  End  = SortsClasse.end();

  EcrireElementConteneur< Sort, FlotMessage > ecrireSort( &debug() );
  
  for_each( SortsClasse.begin(), SortsClasse.end(), ecrireSort );

  sort(Begin, End);
  
  debug() << "Tri effectué" << endmsg;

  it = unique(Begin, End);

  SortsClasse.erase( it, End );
    
  for_each( SortsClasse.begin(), SortsClasse.end(), ecrireSort );

  func() << "Barde::ajoutSorts -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**
 * Permet de gérer les compétences martiales, càd lesquelles sont
 * accessibles à quel coût.
 *
 * Un Barde peut prendre n'importe quelle arme pour 3 pp.
 */
void Barde::prixAcces(map<string, unsigned>*& Map) const
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Barde::prixAcces -> début" << endmsg;

  map<string, unsigned>::const_iterator mapIt, mapBegin(Map -> begin()),
    mapEnd(Map -> end());

  for (mapIt = mapBegin; mapIt != mapEnd; mapIt++)
    {
      lfunc() << mapIt -> first << endmsg;
    }
  Map -> operator[]("Barde") = 3;
  
  func() << "Barde::prixAcces -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

unsigned Barde::pourcent(const bool& lvlUp) const
{
  if ( lvlUp )
    return 15;
  else
    return 20;
}

string Barde::scoreAdditionnel(const unsigned& i) const
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Barde::scoreAdditionnel -> début" << endmsg;

  string resultat( "" );

  if ( Comp[ i ].nom() == "Utilisation de parchemins (niv 10)" ||
       Comp[ i ].nom() == "Utilisation de parchemins" )
    {
      switch( Niveau )
	{
	case 1:
	case 2:
	  resultat = "10";
	  break;
	case 3:
	case 4:
	  resultat = "20";
	  break;
	case 5:
	case 6:
	  resultat = "30";
	  break;
	case 7:
	  resultat = "40";
	  break;
	case 8:
	  resultat = "50";
	  break;
	case 9:
	  resultat = "60";
	  break;
	case 10:
	  resultat = "70";
	  break;
	default:
	  resultat = "80";
	}
    }

  func() << "Barde::scoreAdditionnel -> fin" << endmsg;
  /*Debug::*/depileNiveau();

  return resultat;
}

unsigned Barde::aSpecialisation() const
{
  return find( Competences.begin(), Competences.end(), 13 ) !=
    Competences.end() ? 1 : 0;
}
